# -*- coding: utf-8 -*-
# @Time    : 2024/8/29 8:53
# @Author  : Alvin
# @File    : resources.py

from flask import jsonify, request, current_app, g, send_file
from werkzeug.datastructures import CombinedMultiDict
from werkzeug.utils import secure_filename
from app.libs.error_code import Success, NotFound, ResourceOperationError
from app.libs.minio_client import MinioClient
from app.libs.redprint import Redprint
from app.libs.token_auth import auth
from app.libs.calculate import check_has_enough_points_to_download
from app.models.points_log import PointsLog
from app.validators.forms import UploadForm
from app.libs.utils import generate_md5_filename
from app.models.resources import Resource
from app.models.users import User
from app.models.downloads import Download
from app.libs.enums import PointsLogReason
from io import BytesIO
api = Redprint("resource")


def get_resource_from_minio(resource):
    filepath = resource.file_path
    bucket_name = filepath.split('/')[0]
    object_name = filepath.split('/')[1]

    # 获取 MinIO 配置信息
    endpoint = current_app.config.get('MINIO_ENDPOINT')
    access_key = current_app.config.get('MINIO_ACCESS_KEY')
    secret_key = current_app.config.get('MINIO_SECRET_KEY')

    # 实例化 MinIO 客户端
    minio_client = MinioClient(
        endpoint,
        access_key=access_key,
        secret_key=secret_key,
        secure=False
    )

    # 获取对象存储中的文件
    file_data = minio_client.download_file(bucket_name, object_name)

    secured_filename = secure_filename(resource.resource_name)
    # 设置合适的 Content-Disposition 头部，让浏览器知道这是一个文件下载响应
    content_disposition = f'attachment; filename="{secured_filename}"'
    return send_file(
        file_data,
        mimetype='application/octet-stream',  # 这里可能需要根据文件类型调整
        as_attachment=True,
        download_name=secured_filename
        # content_disposition=content_disposition
    )
@api.route('/download/<int:resource_id>')
@auth.login_required()
def download_resources(resource_id):
    # 先获取用户ID
    uid = g.user.uid
    # 获取当前user对象
    user = User.query.filter_by(id=uid).first()
    if not user:
        return NotFound('用户未找到!')
        # 根据 resource_id 获取资源信息，这里需要您根据实际情况查询数据库
    resource = Resource.query.filter_by(resource_id=resource_id).first()
    if not resource:
        return NotFound('未找到该资源!')
    # 查看是否是已经下载过的资源
    if Download.query.filter_by(user_id=uid, resource_id=resource_id).first():
            # 用户已经下载过, 无需扣余额
            return get_resource_from_minio(resource)

    # 获取资源需要的积分
    required_points = resource.required_points
    print(f'required_points: {required_points}')

    is_enough, points_balance, remaining_points = check_has_enough_points_to_download(user, required_points)
    if not is_enough:
        return ResourceOperationError(msg='余额不足!')
    Download.insert_download_record(uid, resource_id, required_points)
    PointsLog.insert_points_log(uid, points_balance, -1 * required_points, remaining_points, PointsLogReason.DOWNLOAD_RESOURCE.value)
    user.update_balance_points(remaining_points)
    return get_resource_from_minio(resource)
@api.route('/upload', methods=['POST'])
@auth.login_required()
def upload_resources():
    form = UploadForm(CombinedMultiDict([request.form, request.files])).validate_for_api()
    file = form.file.data
    endpoint = current_app.config.get('MINIO_ENDPOINT')
    access_key = current_app.config.get('MINIO_ACCESS_KEY'),
    secret_key = current_app.config.get('MINIO_SECRET_KEY'),
    minio_bucket_name = current_app.config.get('MINIO_BUCKET_NAME')
    if isinstance(access_key, tuple):
        access_key = access_key[0]
    if isinstance(secret_key, tuple):
        secret_key = secret_key[0]
    # 因为我们目前使用的是http，并非https，所有secure要设置为False，否则会报错
    minio_client = MinioClient(
        endpoint,
        access_key,
        secret_key,
        secure=False)
    filename = file.filename
    file_parts = filename.rsplit('.', 1)  # 使用 rsplit 从右侧开始分割，并限制分割次数为 1

    # 检查分割后的列表长度，确保有扩展名
    if len(file_parts) == 2:
        base_name, file_extension = file_parts
        file_extension = file_extension.lower()  # 转换为小写
    else:
        # 如果没有扩展名，设置为一个空字符串或其他占位符
        file_extension = ""
    new_filename = generate_md5_filename(file, file_extension)
    # print(f'new_filename: {new_filename}')
    is_upload_success = minio_client.upload_file(file=file, bucket_name=minio_bucket_name, object_name=new_filename)
    filepath = minio_bucket_name + '/' + new_filename
    description = form.description.data
    required_points = form.required_points.data
    print(f'description: {description}')
    # print(f'secured_filename: {secured_filename}')
    # 通过g拿到user, 因为鉴权的时候我们存储了一个namedtuple赋值给了g.user
    uid = g.user.uid
    print(f'uid: {uid}')
    if is_upload_success:
        # 将记录插入数据库
        Resource.insert_upload_record(uid, filename, filepath, description, required_points)
        return Success(msg="上传成功!")

